use aho_corasick::{AhoCorasick, AhoCorasickKind, MatchKind, PatternID};
use log::info;
use rand::Rng;
use std::vec;
// 添加 rayon 并行处理库
use rayon::prelude::*;
// 添加文件操作相关库
use std::fs::File;
use std::io::{BufRead, BufReader};
use aho_corasick::AhoCorasickKind::{NoncontiguousNFA, DFA};
// 添加时间处理库用于性能统计
use std::time::Instant;

// 生成随机字符串的函数
fn generate_random_string(len: usize) -> String {
    const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
    let mut rng = rand::rng();

    (0..len)
        .map(|_| {
            let idx = rng.random_range(0..CHARSET.len());
            CHARSET[idx] as char
        })
        .collect()
}
fn main() {
    println!("Hello, world!");
    env_logger::builder()
        .filter_level(log::LevelFilter::Info)
        .init();

    // 定义要搜索的模式字符串数组
    //let patterns = &["apple", "maple", "Snapple"];
    let mut patterns: Vec<String> = vec::Vec::new();

    // 从文件读取公司名称作为模式
    // 打开公司名称语料库文件，如果打开失败则panic
    let file = File::open("./Company-Names-Corpus（480W）/Company-Names-Corpus（480W）.txt")
        .expect("无法打开文件");
    // 创建带缓冲的文件读取器以提高读取效率
    let reader = BufReader::new(file);

    // 逐行读取文件内容并处理
    for line in reader.lines() {
        // 处理读取到的每一行
        if let Ok(content) = line {
            // 跳过空行和注释行
            if !content.is_empty() && !content.starts_with("﻿") && !content.starts_with("//") {
                patterns.push(content);
            }
        }
    }


    // 如果文件读取失败或没有足够数据，使用默认模式
    patterns.push("apple".to_string());
    patterns.push("maple".to_string());
    patterns.push("Snapple".to_string());

    let mut rng = rand::rng();
    // 生成100万个随机字符串并添加到patterns向量中
    // 每个字符串的长度在5到11个字符之间随机生成
    if patterns.len() < 100 {
        for _ in patterns.len()..100_000 {
            let string = generate_random_string(rng.random_range(5..12));
            patterns.push(string);
        }
    }

    // 创建Aho-Corasick自动机实例，用于多模式字符串匹配
    info!("start build len:{}", patterns.len());
    //let ac = AhoCorasick::new(patterns).unwrap();

    let ac: AhoCorasick = AhoCorasick::builder()
        //.start_kind(DFA)
        //.kind(Option::from(AhoCorasickKind::DFA))//程序崩溃
        //.kind(Option::from(NoncontiguousNFA))//内存多
        // 配置正则表达式引擎的预过滤选项，启用预过滤可以提高匹配性能
        .prefilter(true)
        // 设置匹配语义为"最左优先"，即在多个可能的匹配中选择最左边且最长的匹配结果
        .match_kind(MatchKind::LeftmostLongest)
        // 使用指定的模式构建正则表达式引擎实例
        .build(patterns)
        // 解包构建结果，如果构建失败则会panic
        .unwrap();

    // 记录构建完成后的统计信息
    // 输出AC自动机的模式串数量和内存使用情况
    info!(
        "end build 模式串数量: {},内存使用: {}",
        ac.patterns_len(),
        ac.memory_usage()
    );

    let mut haystack_list = Vec::<String>::new();
    for j in 0..10000 {
        // 定义要在其中搜索的文本字符串
        let string1 = "Nobody likes maple in their apple flavored Snapple.".repeat(10000 + j);
        haystack_list.push(string1);
    }
    
    // 计算总数据量（字节）
    let total_bytes: usize = haystack_list.iter().map(|s| s.len()).sum();
    
    // 使用 rayon 并行处理所有文本的匹配计数
      // 记录开始查找的日志，输出待查找字符串列表的长度
    info!("start find {}", haystack_list.len());

    // 记录开始时间
    let start_time = Instant::now();
    
    // 使用并行迭代统计所有字符串中匹配模式的数量
    // 通过AC自动机算法在多个字符串中并行查找模式串出现的总次数
    let count: usize = haystack_list
        .par_iter() // 并行迭代
        .map(|string1| {
            let haystack = string1.as_str();
            ac.find_iter(haystack).count()
        })
        .sum();
        
    // 计算耗时
    let elapsed = start_time.elapsed();
    
    // 计算每秒处理的字节数
    let bytes_per_second = (total_bytes as f64 / elapsed.as_secs_f64()) as usize;

    // 记录查找结束的日志，输出找到的匹配总数
    info!("end find, find {}", count);
    
    // 输出性能统计信息
    info!(
        "性能统计: 处理 {} 字节数据，耗时 {:?}，每秒处理 {} 字节",
        total_bytes, elapsed, bytes_per_second
    );


    // 存储匹配结果的向量，每个元素包含模式ID、匹配起始位置和结束位置
    // let mut matches = vec![];
    //
    // for mat in find_iter {
    //     matches.push((mat.pattern(), mat.start(), mat.end()));
    // }
    // 验证匹配结果是否正确
    // 预期找到三个匹配项：
    // 1. "maple" 在位置13-18，模式ID为1
    // 2. "apple" 在位置28-33，模式ID为0
    // 3. "Snapple" 在位置43-50，模式ID为2
    // assert_eq!(
    //     matches,
    //     vec![
    //         (PatternID::must(1), 13, 18),
    //         (PatternID::must(0), 28, 33),
    //         (PatternID::must(2), 43, 50),
    //     ]
    // );
}